//使用DAC输出电压，ADC2读取电压值

#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "esp_system.h"

#define DAC_EXAMPLE_CHANNEL CONFIG_EXAMPLE_DAC_CHANNEL
#define ADC2_EXAMPLE_CHANNEL CONFIG_EXAMPLE_ADC2_CHANNEL

#if CONFIG_IDF_TARGET_ESP32
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
#elif CONFIG_IDF_TARGET_ESP32S2
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
#elif CONFIG_IDF_TARGET_ESP32S3
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
#endif

void app_main(void)
{
    uint8_t output_data = 0;
    int read_raw;
    esp_err_t r;

    gpio_num_t adc_gpio_num, dac_gpio_num;

    r = adc2_pad_get_io_num(ADC2_EXAMPLE_CHANNEL, &adc_gpio_num); // Get the GPIO number of a specific ADC2 channel.
    assert(r == ESP_OK);
    r = dac_pad_get_io_num(DAC_EXAMPLE_CHANNEL, &dac_gpio_num); // Get the GPIO number of a specific DAC channel.
    assert(r == ESP_OK);

    printf("ADC2 channel %d @ GPIO %d, DAC channel %d @ GPIO %d.\n", ADC2_EXAMPLE_CHANNEL, adc_gpio_num,
           DAC_EXAMPLE_CHANNEL + 1, dac_gpio_num);

    dac_output_enable(DAC_EXAMPLE_CHANNEL); // 使能DAC通道

    // be sure to do the init before using adc2.
    printf("adc2_init...\n");
    adc2_config_channel_atten(ADC2_EXAMPLE_CHANNEL, ADC_ATTEN_11db); // 设置ADC2通道的衰减值

    vTaskDelay(2 * portTICK_PERIOD_MS);

    printf("start conversion.\n");
    while (1)
    {
        dac_output_voltage(DAC_EXAMPLE_CHANNEL, output_data++);//   设置DAC输出电压
        r = adc2_get_raw(ADC2_EXAMPLE_CHANNEL, width, &read_raw);// 读取ADC2通道的原始值
        if (r == ESP_OK)
        {
            printf("%d: %d\n", output_data, read_raw);
        }
        else if (r == ESP_ERR_INVALID_STATE)
        {
            printf("%s: ADC2 not initialized yet.\n", esp_err_to_name(r));
        }
        else if (r == ESP_ERR_TIMEOUT)
        {
            // This can not happen in this example. But if WiFi is in use, such error code could be returned.
            printf("%s: ADC2 is in use by Wi-Fi.\n", esp_err_to_name(r));
        }
        else
        {
            printf("%s\n", esp_err_to_name(r));
        }

        vTaskDelay(2 * portTICK_PERIOD_MS);
    }
}
